package com.example.jobtask.scheduler;

import com.example.jobtask.entity.JobTask;
import com.example.jobtask.executor.TaskExecutor;
import com.example.jobtask.repository.JobTaskRepository;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;

/**
 * 任务调度管理器
 */
@Component
public class TaskScheduleManager {
    
    private static final Logger logger = LoggerFactory.getLogger(TaskScheduleManager.class);
    
    @Autowired
    private Scheduler scheduler;
    
    @Autowired
    private JobTaskRepository jobTaskRepository;
    
    @Autowired
    private TaskExecutor taskExecutor;
    
    /**
     * 添加任务到调度器
     */
    public void scheduleTask(JobTask jobTask) {
        try {
            // 创建JobDetail
            JobDetail jobDetail = JobBuilder.newJob(DynamicTaskJob.class)
                    .withIdentity(getJobKey(jobTask))
                    .usingJobData("taskId", jobTask.getId())
                    .build();
            
            // 创建Trigger
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(jobTask))
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTask.getCronExpression()))
                    .build();
            
            // 调度任务
            scheduler.scheduleJob(jobDetail, trigger);
            
            // 更新下次执行时间
            updateNextExecutionTime(jobTask, trigger);
            
            logger.info("任务已添加到调度器: {}", jobTask.getTaskName());
            
        } catch (SchedulerException e) {
            logger.error("添加任务到调度器失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("添加任务到调度器失败", e);
        }
    }
    
    /**
     * 从调度器中移除任务
     */
    public void unscheduleTask(JobTask jobTask) {
        try {
            scheduler.unscheduleJob(getTriggerKey(jobTask));
            scheduler.deleteJob(getJobKey(jobTask));
            logger.info("任务已从调度器中移除: {}", jobTask.getTaskName());
        } catch (SchedulerException e) {
            logger.error("从调度器中移除任务失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("从调度器中移除任务失败", e);
        }
    }
    
    /**
     * 暂停任务
     */
    public void pauseTask(JobTask jobTask) {
        try {
            scheduler.pauseJob(getJobKey(jobTask));
            logger.info("任务已暂停: {}", jobTask.getTaskName());
        } catch (SchedulerException e) {
            logger.error("暂停任务失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("暂停任务失败", e);
        }
    }
    
    /**
     * 恢复任务
     */
    public void resumeTask(JobTask jobTask) {
        try {
            scheduler.resumeJob(getJobKey(jobTask));
            logger.info("任务已恢复: {}", jobTask.getTaskName());
        } catch (SchedulerException e) {
            logger.error("恢复任务失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("恢复任务失败", e);
        }
    }
    
    /**
     * 立即执行任务
     */
    public void triggerTaskNow(JobTask jobTask) {
        try {
            scheduler.triggerJob(getJobKey(jobTask));
            logger.info("任务已立即触发: {}", jobTask.getTaskName());
        } catch (SchedulerException e) {
            logger.error("立即触发任务失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("立即触发任务失败", e);
        }
    }
    
    /**
     * 重新调度任务（更新cron表达式）
     */
    public void rescheduleTask(JobTask jobTask) {
        try {
            TriggerKey triggerKey = getTriggerKey(jobTask);
            
            // 创建新的Trigger
            Trigger newTrigger = TriggerBuilder.newTrigger()
                    .withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTask.getCronExpression()))
                    .build();
            
            // 重新调度
            scheduler.rescheduleJob(triggerKey, newTrigger);
            
            // 更新下次执行时间
            updateNextExecutionTime(jobTask, newTrigger);
            
            logger.info("任务已重新调度: {}", jobTask.getTaskName());
            
        } catch (SchedulerException e) {
            logger.error("重新调度任务失败: " + jobTask.getTaskName(), e);
            throw new RuntimeException("重新调度任务失败", e);
        }
    }
    
    /**
     * 检查任务是否存在于调度器中
     */
    public boolean isTaskScheduled(JobTask jobTask) {
        try {
            return scheduler.checkExists(getJobKey(jobTask));
        } catch (SchedulerException e) {
            logger.error("检查任务是否存在失败: " + jobTask.getTaskName(), e);
            return false;
        }
    }
    
    /**
     * 获取JobKey
     */
    private JobKey getJobKey(JobTask jobTask) {
        return JobKey.jobKey(jobTask.getTaskName(), "DEFAULT");
    }
    
    /**
     * 获取TriggerKey
     */
    private TriggerKey getTriggerKey(JobTask jobTask) {
        return TriggerKey.triggerKey(jobTask.getTaskName(), "DEFAULT");
    }
    
    /**
     * 更新下次执行时间
     */
    private void updateNextExecutionTime(JobTask jobTask, Trigger trigger) {
        Date nextFireTime = trigger.getNextFireTime();
        if (nextFireTime != null) {
            LocalDateTime nextExecution = LocalDateTime.ofInstant(
                nextFireTime.toInstant(), ZoneId.systemDefault());
            jobTask.setNextExecutionAt(nextExecution);
            jobTaskRepository.save(jobTask);
        }
    }
    
    /**
     * 动态任务Job实现
     */
    public static class DynamicTaskJob implements Job {
        
        private static final Logger logger = LoggerFactory.getLogger(DynamicTaskJob.class);
        
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            JobDataMap dataMap = context.getJobDetail().getJobDataMap();
            Long taskId = dataMap.getLong("taskId");
            
            try {
                // 获取Spring上下文中的bean
                JobTaskRepository repository = ApplicationContextProvider.getBean(JobTaskRepository.class);
                TaskExecutor executor = ApplicationContextProvider.getBean(TaskExecutor.class);
                
                // 获取任务信息
                JobTask jobTask = repository.findById(taskId)
                        .orElseThrow(() -> new JobExecutionException("任务不存在: " + taskId));
                
                // 检查任务状态
                if (jobTask.getStatus() != JobTask.TaskStatus.ACTIVE) {
                    logger.info("任务状态不是ACTIVE，跳过执行: {}", jobTask.getTaskName());
                    return;
                }
                
                // 执行任务
                Object result = executor.executeTask(jobTask);
                
                // 更新执行信息
                jobTask.setLastExecutedAt(LocalDateTime.now());
                jobTask.setExecutionCount(jobTask.getExecutionCount() + 1);
                repository.save(jobTask);
                
                logger.info("任务执行完成: {}, 执行次数: {}", 
                    jobTask.getTaskName(), jobTask.getExecutionCount());
                
            } catch (Exception e) {
                logger.error("执行任务时发生异常: " + taskId, e);
                throw new JobExecutionException("执行任务失败", e);
            }
        }
    }
}